/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#pragma once

#include <baja/common.hpp>
#include <baja/db/db.h>
#include <dependencies/includes/ink_renderer_interface.h>
#include <journal/models/types.h>

namespace journal { namespace model { namespace db {

namespace b = baja;
namespace s = baja::storage;
namespace bi = baja::ink;

struct icommon_table : public b::ibase
{
    BAJA_INTERFACE_NOTAG(icommon_table);

    virtual void initialize() = 0;
    virtual std::wstring name() = 0;
    virtual std::shared_ptr<s::iengine> dbEngine() = 0;
    virtual std::shared_ptr<s::itable> tableDefinition() = 0;
    virtual std::shared_ptr<std::vector<std::shared_ptr<s::icell>>> stagingRow() = 0;
    virtual std::shared_ptr<s::iindex> primaryIndex() = 0;

    virtual unsigned int getNextId() = 0;

    virtual void insert(std::shared_ptr<std::vector<std::shared_ptr<s::icell>>> stagingRow) = 0;

    virtual void update(std::shared_ptr<std::vector<std::shared_ptr<s::icell>>> stagingRow, 
                        b::uint32 criteriaCount) = 0;

    virtual void read(std::shared_ptr<std::vector<std::shared_ptr<s::icell>>> stagingRow, 
                      b::uint32 criteriaCount,
                      std::shared_ptr<s::iresult> result) = 0;

    virtual void read(std::shared_ptr<s::iindex> keyIndex,
                      std::shared_ptr<std::vector<std::shared_ptr<s::icell>>> stagingRow, 
                      b::uint32 criteriaCount,
                      bool assumeSingleMatch,
                      std::shared_ptr<s::iresult> result) = 0;

    virtual void readAll(std::shared_ptr<s::iresult> result) = 0;

    virtual void readIds(std::shared_ptr<std::vector<std::shared_ptr<s::icell>>> criteriaRow,
                         std::shared_ptr<s::icolumn> idColumn,
                         std::vector<b::uint32>& ids) = 0;

    virtual void readActiveIds(
        std::shared_ptr<std::vector<std::shared_ptr<s::icell>>> criteriaRow,
        std::shared_ptr<s::icolumn> idColumn,
        std::shared_ptr<s::icolumn> activeColumn,
        std::vector<b::uint32>& ids) = 0;

    virtual void dispose(
        std::shared_ptr<std::vector<std::shared_ptr<s::icell>>> criteriaRow) = 0;

    virtual void disposeInactiveRecords(
        std::shared_ptr<s::iindex> keyIndex,
        std::shared_ptr<std::vector<std::shared_ptr<s::icell>>> criteriaRow,
        b::uint32 criteriaCount,
        bool assumeSingleMatch) = 0;

    virtual void disposeAll() = 0;
};

struct icommon_table_client : public b::ibase
{
    BAJA_INTERFACE_NOTAG(icommon_table_client);

    virtual void defineColumns(std::shared_ptr<s::itable> table) = 0;
    virtual void defineIndexColumns(std::shared_ptr<s::iindex> primaryKeyIndex) = 0;
    virtual void defineRowCells(std::shared_ptr<std::vector<std::shared_ptr<s::icell>>> row) = 0;
};

struct ibase_table : public b::ibase
{
    BAJA_INTERFACE_NOTAG(ibase_table);

    virtual std::shared_ptr<icommon_table> common() = 0;
};

struct inotebook_table : public ibase_table
{
    BAJA_INTERFACE_NOTAG(inotebook_table);

    virtual void write(const std::vector<size_t>& v) = 0;
    virtual void read(std::vector<size_t>& v) = 0;
};

struct ipage_table : public ibase_table
{
    BAJA_INTERFACE_NOTAG(ipage_table);

    virtual void readIds(
        std::vector<b::uint32>& ids) = 0;

    virtual void insert(
        const b::uint32& pageId,
        const b::Boolean& linkedData,
        const b::Boolean& thumbnailUpToDate,
        const b::uint32& pagePaperType) = 0;

    virtual void updateThumbnail(
        const b::uint32 pageId,
        const b::Boolean& thumbnailUpToDate,
        const s::binary_blob& inBlob) = 0;

    virtual void load(
        const b::uint32& pageId,
        b::Boolean& pageLinkedData,
        b::uint32& pagePaperType,
        b::Boolean& pageThumbnailUpToDate,
        std::vector<b::uint32>& pagePhotoIds) = 0;

    virtual void loadThumbnail(
        const b::uint32 pageId,
        b::Boolean& pageThumbnailUpToDate,
        s::binary_blob& inBlob) = 0;

    virtual void dispose(
        b::uint32 pageId) = 0;

    virtual void updateLinkedData(
        const b::uint32 pageId,
        const b::Boolean& linkedData) = 0;

    virtual void updatePagePaperType(
        const b::uint32& pageId,
        const b::uint32& pagePaperType) = 0;

    virtual void updateThumbnailStatus(
        const b::uint32& pageId,
        const b::Boolean& thumbnailUpToDate) = 0;
    
    virtual void updatePhotoIds(
        const b::uint32 pageId,
        const std::vector<b::uint32>& pagePhotoIds) = 0;
};

struct iink_surface_table : public ibase_table
{
    BAJA_INTERFACE_NOTAG(iink_surface_table);

    virtual void readIds(b::uint32 pageId,
                         std::vector<b::uint32>& ids) = 0;

    virtual void insert(unsigned int inkSurfaceId,
                        unsigned int pageId) = 0;

    virtual void appendInkStroke(
        b::uint32 inkSurfaceId,
        b::uint32 pageId,
        b::uint32 allStrokesSize,
        s::binary_blob& inBlob) = 0;

    virtual void replaceInkStrokes(
        b::uint32 inkSurfaceId,
        b::uint32 pageId,
        s::binary_blob& inBlob) = 0;

    // no other attributes to return, but we have load() for consistency.
    virtual void load(unsigned int inkSurfaceId,
                      unsigned int pageId) = 0;

    virtual void loadInkStrokes(
        b::uint32 inkSurfaceId,
        b::uint32 pageId,
        s::binary_blob& outBlob) = 0;

    virtual void dispose(
        b::uint32 inkSurfaceId,
        b::uint32 pageId) = 0;

    virtual void dispose(
        b::uint32 pageId) = 0;
};

struct iink_stroke_table : public ibase_table
{
    BAJA_INTERFACE_NOTAG(iink_stroke_table);

    virtual void readIds(b::uint32 inkSurfaceId,
                         std::vector<b::uint32>& ids) = 0;

    virtual void insert(b::uint32 inkStrokeId, 
                        b::uint32 inkSurfaceId,
                        b::uint64 t0,
                        b::uint32 color,
                        b::float32 width,
                        s::binary_blob& pointsArray) = 0;

    virtual void update(b::uint32 inkStrokeId, 
                        b::uint32 inkSurfaceId,
                        b::uint64 t0,
                        b::uint32 color,
                        b::float32 width,
                        s::binary_blob& pointsArray) = 0;

    virtual void load(b::uint32 inkStrokeId, 
                      b::uint32 inkSurfaceId,
                      b::uint64& t0,
                      b::uint32& color,
                      b::float32& width,
                      std::vector<bi::ink_point>& pointsArray) = 0;
};

struct imedia_file_table : public ibase_table
{
    BAJA_INTERFACE_NOTAG(imedia_file_table);

    virtual void insert(b::uint32 mediaFileId,
                        std::wstring fileName,
                        std::wstring originalFileName) = 0;

    virtual void load(
        b::uint32 mediaFileId,
        std::wstring& fileName,
        std::wstring& originalFileName) = 0;

    virtual bool findMediaFile(
        std::wstring originalFileName,
        b::uint32& mediaFileId,
        std::wstring& localMediaFileName) = 0;

    virtual void disposeUnused(
        const std::set<b::uint32>& inUseSet,
        std::vector<std::wstring>& filesToDispose) = 0;
};

struct iphoto_table : public ibase_table
{
    BAJA_INTERFACE_NOTAG(iphoto_table);

    virtual void readActiveIds(
        b::uint32 pageId,
        std::vector<b::uint32>& ids) = 0;

    virtual void insert(b::uint32 photoId,
                        b::uint32 pageId,
                        bool active,
                        b::uint32 mediaFileId,
                        b::float32 scale,
                        b::float32 angle,
                        b::float32 x,
                        b::float32 y) = 0;

    virtual void update(b::uint32 photoId,
                        b::uint32 pageId,
                        bool active,
                        b::uint32 mediaFileId,
                        b::float32 scale,
                        b::float32 angle,
                        b::float32 x,
                        b::float32 y) = 0;

    virtual void load(b::uint32 photoId,
                      b::uint32 pageId,
                      bool& active,
                      b::uint32& mediaFileId,
                      b::float32& scale,
                      b::float32& angle,
                      b::float32& x,
                      b::float32& y) = 0;

    virtual void dispose(
        b::uint32 photoId,
        b::uint32 pageId) = 0;

    virtual void dispose(
        b::uint32 pageId) = 0;

    virtual void disposeInactiveRecords() = 0;

    virtual void getMediaFileIds(
        std::set<b::uint32>& mediaFileIds) = 0;
};

}}} // journal::model::db
